package com.tripspins.app;

import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.tripspins.app.bo.Attachment;
import com.tripspins.app.bo.CurrentWeather;
import com.tripspins.app.bo.Pin;
import com.tripspins.app.bo.Route;
import com.tripspins.app.bo.Trip;
import com.tripspins.app.bo.User;
import com.tripspins.app.dao.TripDAO;
import com.tripspins.app.dao.UserDAO;
import com.tripspins.app.exception.NoConnectionException;
import com.tripspins.app.exception.OfflineModeException;
import com.tripspins.app.helper.ConstantsHelper;
import com.tripspins.app.helper.DbHelper;
import com.tripspins.app.helper.FILE_TYPE;
import com.tripspins.app.helper.FileHelper;
import com.tripspins.app.helper.MapsAPIHelper;
import com.tripspins.app.helper.MenuHelper;
import com.tripspins.app.helper.SocialHelper;
import com.tripspins.app.helper.SyncHelper;
import com.tripspins.app.helper.ThumbnailsHelper;
import com.tripspins.app.interfaces.OnTaskCompleted;
import com.facebook.UiLifecycleHelper;
import com.facebook.widget.FacebookDialog;
import com.facebook.widget.ProfilePictureView;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

import java.util.ArrayList;
import java.util.HashMap;


public class MapActivity extends Activity implements OnTaskCompleted {

    Route route;
    HashMap<String,Pin> markersMap;
    DbHelper dbHelper;
    Trip trip;
    Trip tripParent;
    Pin detailPin;
    GoogleMap map;
    final Context context = this;
    boolean isOnTheRoad;
    long tripId;

    private UiLifecycleHelper uiHelper;
    //TripDetails
    TextView tripTitle;
    TextView tripDays;
    TextView tripCountPins;
    TextView tripCountAttachments;
    LinearLayout tripScrollAttachments;
    RelativeLayout tripDetailLayout;


    //PinDetails
    TextView pinTitle;
    TextView pinNote;
    TextView pinAddress;
    TextView pinDegrees;
    ImageView pinWeatherIcon;
    LinearLayout pinScrollAttachments;
    RelativeLayout pinDetailLayout;
    MapsAPIHelper mapsHelper;
    Intent myIntent;
    SQLiteDatabase database;
    TripDAO tripDao;
    UserDAO userDao;
    MapFragment mapFragment;
    static MapActivity mapActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_map_details);

        uiHelper = new UiLifecycleHelper(this, null);
        uiHelper.onCreate(savedInstanceState);

        mapActivity = this;
        mapsHelper = new MapsAPIHelper(this);
        dbHelper = new DbHelper(this);
        myIntent = getIntent();

        database = dbHelper.getReadableDatabase();
        tripDao = new TripDAO(database);
        isOnTheRoad = tripDao.isOnTheRoad();

        userDao = new UserDAO(database);
        tripDao = new TripDAO(database);
        User loggedUser = userDao.getLoggedUser();
        boolean isAuthenticated = loggedUser != null;

        MenuHelper.loadMenu(this, isOnTheRoad, isAuthenticated);
        FragmentManager mng=getFragmentManager();
        mapFragment =(MapFragment) mng.findFragmentById(R.id.map_details);
        map = mapFragment.getMap();
        markersMap = new HashMap<String, Pin>();

        tripTitle = (TextView)findViewById(R.id.map_trip_title);
        tripDays = (TextView)findViewById(R.id.map_trip_days);
        tripCountPins = (TextView)findViewById(R.id.map_trip_count_pins);
        tripCountAttachments = (TextView)findViewById(R.id.map_trip_count_attachments);
        tripScrollAttachments = (LinearLayout)findViewById(R.id.map_trip_attachments_list);

        pinTitle =  (TextView)findViewById(R.id.map_title_pin);
        pinAddress =  (TextView)findViewById(R.id.map_address_pin);
        pinDegrees =  (TextView)findViewById(R.id.map_weather_degrees_pin);
        pinNote =  (TextView)findViewById(R.id.map_note_pin);
        pinScrollAttachments = (LinearLayout)findViewById(R.id.map_attachments_list_pin);
        pinWeatherIcon = (ImageView)findViewById(R.id.map_weather_img_pin);
        tripDetailLayout = (RelativeLayout)findViewById(R.id.map_layout_trip);
        pinDetailLayout = (RelativeLayout)findViewById(R.id.map_layout_pin);

        if (savedInstanceState!= null && savedInstanceState.getParcelable("trip") != null)
            trip = savedInstanceState.getParcelable("trip");
    }


    @Override
    protected void onStart() {
        super.onStart();

        if(trip == null)
        {
            tripId = myIntent.getLongExtra("tripId",0);
            tripParent = tripDao.getTrip(tripId);
            if (myIntent.getParcelableExtra("pin") != null)
                detailPin = myIntent.getParcelableExtra("pin");
            else
                detailPin = null;
            if (detailPin == null){ //Trip Detail
                showTripDetail(true);
                if(tripId == 0)
                    trip = tripDao.getTrip();
                else
                    trip = tripDao.getTrip(tripId);

                if(map != null) {
                    for (Pin p : trip.getPins()) {
                        MarkerOptions markerOptions = mapsHelper.getMarker(p);
                        Marker marker = map.addMarker(markerOptions);
                        markersMap.put(marker.getId(), p);
                    }

                    map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
                        @Override
                        public void onInfoWindowClick(Marker marker) {
                            Pin p = markersMap.get(marker.getId());
                            loadPinData(p);
                        }
                    });
                }
                loadTripData(trip);
            }
            else //Pin detail
            {
                showTripDetail(false);
                if(map != null) {
                    MarkerOptions markerOptions = mapsHelper.getMarker(detailPin);
                    Marker marker = map.addMarker(markerOptions);
                    markersMap.put(marker.getId(), detailPin);

                    map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
                        @Override
                        public void onInfoWindowClick(Marker marker) {
                            Pin p = markersMap.get(marker.getId());
                            loadPinData(p);
                        }
                    });
                }
                loadPinData(detailPin);
            }

            mapFragment.getView().getViewTreeObserver().addOnGlobalLayoutListener(
                    new ViewTreeObserver.OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            CameraUpdate center = null;
                            if(trip != null) {
                                LatLngBounds bound = new LatLngBounds(trip.getPinFinish().getLatLng(), trip.getPinFinish().getLatLng());
                                center = CameraUpdateFactory.newLatLngZoom(trip.getPinFinish().getLatLng(), 12.0f);
                            }
                            else
                            {
                                LatLngBounds bound = new LatLngBounds(detailPin.getLatLng(), detailPin.getLatLng());
                                center = CameraUpdateFactory.newLatLngZoom(detailPin.getLatLng(), 12.0f);
                            }
                            map.moveCamera(center);

                            /*map.snapshot(new GoogleMap.SnapshotReadyCallback() {
                                @Override
                                public void onSnapshotReady(Bitmap bitmap) {
                                    File mapThumbnail = new FileHelper(context).getMapThumbnail(trip.getId());
                                    if(!mapThumbnail.exists()) {
                                        FileHelper fileHelper = new FileHelper(context);
                                        ThumbnailsHelper.saveBitmap(bitmap, fileHelper.getMapThumbnail(trip.getId()), context);
                                    }

                                }
                            });*/


                        }
                    });

        }

        database.close();


    }

    private void showTripDetail(boolean tripDetailVisible) {
        if(tripDetailVisible) {
            tripDetailLayout.setVisibility(View.VISIBLE);
            pinDetailLayout.setVisibility(View.GONE);
        }
        else
        {
            tripDetailLayout.setVisibility(View.GONE);
            pinDetailLayout.setVisibility(View.VISIBLE);
        }
    }

    private void loadTripData(Trip trip) {
        showTripDetail(true);
        tripTitle.setText(trip.getDescription());
        tripCountAttachments.setText(String.valueOf(trip.getCountAttachments()));
        tripCountPins.setText(String.valueOf(trip.getPins().size()));
        int dayCount = trip.getCountDays();
        tripDays.setText( tripDays.getText().toString().replace("?", String.valueOf(dayCount)));
        if (dayCount <= 1)
            tripDays.setText( tripDays.getText().toString().replace("d",context.getString(R.string.day_on_the_road)));
        else
            tripDays.setText( tripDays.getText().toString().replace("d",context.getString(R.string.days_on_the_road)));
        loadAttachmentsThumbnails(trip.getPins());



    }

    private static class AuxParam
    {
        public ArrayList<Pin> pins;
        public LinearLayout scroll;
        public Context context;
    }

    private void loadAttachmentsThumbnails(ArrayList<Pin> pins) {
        tripScrollAttachments.removeAllViews();
        AuxParam param = new AuxParam();
        param.pins = pins;
        param.scroll = tripScrollAttachments;
        param.context = this;

        new AsyncTask<AuxParam,Void, ArrayList<View>>()
        {
            AuxParam param;
            ArrayList<View> list;

            @Override
            protected ArrayList<View> doInBackground(AuxParam... params) {
                param = params[0];
                ImageView thumbnail;
                list = new ArrayList<View>();
                for (Pin p : param.pins) {
                    for (Attachment a : p.getAttachments()) {

                        final Attachment att = a;
                        thumbnail = new ImageView(param.context);
                        thumbnail.setMaxHeight(400);
                        thumbnail.setMaxWidth(400);
                        thumbnail.setScaleType(ImageView.ScaleType.FIT_START);
                        thumbnail.setPadding(0, 3, 3, 0);

                        switch (a.getFileType()) {
                            case AUDIO:
                                thumbnail.setImageURI(Uri.parse(a.getThumbnailPath()));
                            case CONTACT:
                                break;
                            case IMAGE:
                                thumbnail.setImageURI(Uri.parse(a.getThumbnailPath()));
                                thumbnail.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        Intent intent = new Intent();
                                        intent.setAction(android.content.Intent.ACTION_VIEW);
                                        intent.setDataAndType(Uri.parse("file://" + att.getPath()), "image/*");
                                        context.startActivity(intent);
                                    }
                                });
                                /*thumbnail.setOnLongClickListener(new View.OnLongClickListener() {
                                    @Override
                                    public boolean onLongClick(View view) {
                                        if (detailPin != null) {
                                            SocialHelper socialHelper = new SocialHelper();
                                            try {
                                                socialHelper.shareOnFacebook(tripParent.getIdOnServer(), detailPin.getId(), att, mapActivity);
                                            } catch (NoConnectionException e) {
                                                e.printStackTrace();
                                            } catch (OfflineModeException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                        return true;
                                    }
                                });*/
                            case VIDEO:
                                thumbnail.setImageURI(Uri.parse(a.getThumbnailPath()));
                                thumbnail.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        Intent intent = new Intent();
                                        intent.setAction(android.content.Intent.ACTION_VIEW);
                                        intent.setDataAndType(Uri.parse("file://" + att.getPath()), "video/*");
                                        context.startActivity(intent);
                                    }
                                });
                                /*thumbnail.setOnLongClickListener(new View.OnLongClickListener() {
                                    @Override
                                    public boolean onLongClick(View view) {
                                        if (detailPin != null) {
                                            SocialHelper socialHelper = new SocialHelper();
                                            try {
                                                socialHelper.shareOnFacebook(tripParent.getIdOnServer(), detailPin.getId(), att, mapActivity);
                                            } catch (NoConnectionException e) {
                                                e.printStackTrace();
                                            } catch (OfflineModeException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                        return true;
                                    }
                                });*/
                                list.add(thumbnail);
                                break;
                            default:
                                break;


                        }

                    }

                }
                return list;
            }
            @Override
            protected void onPostExecute(ArrayList<View> views) {
                super.onPostExecute(views);
                for (View v : views)
                    tripScrollAttachments.addView(v);

            }
        }.execute(param);

    }


    private void loadAttachmentsThumbnails(Pin p) {

        pinScrollAttachments.removeAllViews();
        ImageView thumbnail;
        ProfilePictureView fbContactPicture;

        for(Attachment a : p.getAttachments())
        {
            if(a.getFileType() == FILE_TYPE.IMAGE ||a.getFileType() == FILE_TYPE.VIDEO)
            {
                final Attachment att = a;
                thumbnail = new ImageView(this);
                thumbnail.setMaxHeight(400);
                thumbnail.setMaxWidth(400);
                thumbnail.setScaleType(ImageView.ScaleType.FIT_START);
                thumbnail.setPadding(0,3,3,0);
                thumbnail.setImageURI(Uri.parse(a.getThumbnailPath()));

                thumbnail.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent();
                        intent.setAction(android.content.Intent.ACTION_VIEW);
                        if (att.getFileType() == FILE_TYPE.IMAGE )
                            intent.setDataAndType(Uri.parse("file://" + att.getPath()), "image/*");
                        else intent.setDataAndType(Uri.parse("file://" + att.getPath()), "video/*");
                        context.startActivity(intent);
                    }

                });
                thumbnail.setOnLongClickListener( new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View view) {
                        if (detailPin != null) {
                            SocialHelper socialHelper = new SocialHelper();
                            try {
                                socialHelper.shareOnFacebook(tripParent.getIdOnServer(), detailPin.getId(), att, mapActivity);
                            } catch (NoConnectionException e) {
                                e.printStackTrace();
                            } catch (OfflineModeException e) {
                                e.printStackTrace();
                            }
                        }
                        return true;
                    }
                });

                pinScrollAttachments.addView(thumbnail);
            }
            else if(a.getFileType() == FILE_TYPE.CONTACT && a.getContact().getContactIdOnSource()!= null)
            {
                fbContactPicture = new ProfilePictureView(this);
                fbContactPicture.setPadding(0,3,3,0);
                fbContactPicture.setProfileId(a.getContact().getContactIdOnSource());
                pinScrollAttachments.addView(fbContactPicture);
            }

        }
    }

    private void loadPinData(Pin p) {
        showTripDetail(false);
        pinTitle.setText(p.getTitle());
        pinNote.setText(p.getTextNote());
        pinAddress.setText(p.getAddressString());
        pinDegrees.setText(String.valueOf(p.getCurrentWeather().getTempC()) + "ºC");
        pinWeatherIcon.setVisibility(View.VISIBLE);
        pinWeatherIcon.setImageURI(Uri.fromFile(p.getWeatherIconUri(this, tripId)));
        loadAttachmentsThumbnails(p);
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.clear();
        if(isOnTheRoad)
            getMenuInflater().inflate(R.menu.menu_on_the_road, menu);
        else
            getMenuInflater().inflate(R.menu.menu_off_the_road, menu);
        return true;
    }


    public void onTaskCompleted(Route route) {
        boolean moveCenter = route != null && route.getPoints().size() > 0;
        trip.setRoute(route);

        try {
            PolylineOptions rectOptions = new PolylineOptions();
            rectOptions.color(Color.parseColor("#C95E18"));



            map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
            map.snapshot(new GoogleMap.SnapshotReadyCallback() {
                @Override
                public void onSnapshotReady(Bitmap bitmap) {
                    FileHelper fileHelper = new FileHelper(context);
                    ThumbnailsHelper.saveBitmap(bitmap, fileHelper.getMapThumbnail(trip.getId()), context);

                }
            });


            /*for (LatLng latLng : trip.getRoute().getPoints()) {
                rectOptions.add(latLng);
            }*/
            for (Pin pin : trip.getPins()) {
                rectOptions.add(pin.getLatLng());
            }




            Polyline rota = map.addPolyline(rectOptions);
            //LocationHelper locationHelper = LocationHelper.getInstance(this, map);

            LatLngBounds bounds = new LatLngBounds(trip.getRoute().getBounds().get(1), trip.getRoute().getBounds().get(0));
            CameraUpdate center = CameraUpdateFactory.newLatLngBounds(bounds, 150);

            if (moveCenter)
            {
                map.moveCamera(center);

            }
            //map.animateCamera(zoom);


        } catch (Exception e) {

        }


    }



    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("trip", trip);
        uiHelper.onSaveInstanceState(outState);



    }


    public void onTaskCompleted(CurrentWeather w)
    {}

    @Override
    public void onTaskCompleted(Bitmap b) {
        //Not used
    }

    @Override
    public void onTaskCompleted(Attachment att) {

        FacebookDialog shareDialog = new FacebookDialog.ShareDialogBuilder(this)
                .setLink(att.getPublicFilePath())
                .setDescription("Shared through Trips&Pins App").build();
        uiHelper.trackPendingDialogCall(shareDialog.present());
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        uiHelper.onActivityResult(requestCode, resultCode, data, new FacebookDialog.Callback() {
            @Override
            public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) {
            }

            @Override
            public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) {
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        uiHelper.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        uiHelper.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        menu.clear();
        if(isOnTheRoad)
            getMenuInflater().inflate(R.menu.menu_map_on_the_road, menu);
        else
            getMenuInflater().inflate(R.menu.menu_map_off_the_road, menu);

        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {

        switch (item.getItemId()) {
            case R.id.menu_new_pin:
                final Intent intentNewPinActivity = new Intent(this,NewPinActivity.class);
                intentNewPinActivity.putExtra("param", ConstantsHelper.PIN_DEFAULT);
                startActivity(intentNewPinActivity );
                return true;

            /*case R.id.menu_settings:
                final Intent intentSettingsActivity = new Intent(this,SettingsActivity.class);
                startActivity(intentSettingsActivity);
                return true;
*/
            case R.id.menu_finish:
                final Intent intentFinishTripActivity = new Intent(this,NewPinActivity.class);
                intentFinishTripActivity.putExtra("param", ConstantsHelper.PIN_FINISH);
                startActivity(intentFinishTripActivity );
                return true;

            case R.id.menu_view_as_list:
                if (detailPin == null) {
                    final Intent intentListPinsActivity = new Intent(this, ListPinsActivity.class);
                    intentListPinsActivity.putExtra("param", trip);
                    startActivity(intentListPinsActivity);
                }else{
                    this.finish();
                }
                return true;
         /*   case R.id.menu_login_fb:
                final Intent intentLoginActivity = new Intent(this, LoginActivity.class);
                startActivity(intentLoginActivity);
                return true;*/
            default:
                DrawerLayout leftMenu = (DrawerLayout)findViewById(R.id.drawer_layout);
                ListView listMenu = (ListView)findViewById(R.id.left_drawer);
                if(leftMenu.isDrawerOpen(listMenu))
                    leftMenu.closeDrawer(listMenu);
                else
                    leftMenu.openDrawer(listMenu);
                return true;
        }    }
    private ArrayList<LatLng> getCurvedLine(LatLng a, LatLng b)
    {
        ArrayList<LatLng> linePoints = new ArrayList<LatLng>();

        LatLng midpoint = new LatLng((a.latitude+b.latitude)/2,(a.longitude + b.longitude)/2);

        double radius = getRadius(a,midpoint);
        double x = 0;
        double y = 0;

        double theta = 0;  // angle that will be increased each loop
        double h = midpoint.latitude;      // x coordinate of circle center
        double k = midpoint.longitude;      // y coordinate of circle center
        double step = 0.005;  // amount to add to theta each time (degrees)

        while (theta < 360)
        {
            x = h + radius * Math.cos(Math.toRadians(theta));
            y = k + radius* Math.sin(Math.toRadians(theta));
            if(isInBetween(a,b,new LatLng(x,y)))
                linePoints.add(new LatLng(x,y));

            theta += step;
        }
        return linePoints;

    }


    private double getRadius(LatLng a, LatLng b) {
        return Math.sqrt(Math.pow(a.latitude - b.latitude, 2.0) + Math.pow(a.longitude - b.longitude, 2.0));
    }

    private boolean isInBetween(LatLng a, LatLng b, LatLng inBetween)
    {
        if (a.latitude >=0 && a.longitude >=0) //A
        {
            if(inBetween.longitude > b.longitude) return true;
            if(inBetween.latitude > a.latitude) return true;

        }
        else if (a.latitude >=0 && a.longitude <=0) //B
        {
            if(inBetween.longitude < a.longitude) return true;
            if(inBetween.latitude < b.latitude) return true;
        }
        else if (a.latitude <=0 && a.longitude >=0) //C
        {
            if(inBetween.longitude > a.longitude) return true;
            if(inBetween.latitude > b.latitude) return true;
        }
        else if (a.latitude <=0 && a.longitude <=0) //D
        {
            if(inBetween.longitude < a.longitude) return true;
            if(inBetween.latitude > b.latitude) return true;
        }
        return false;
    }

    @Override
    public void onBackPressed() {
        if((trip != null && tripDetailLayout.getVisibility() == View.VISIBLE)||trip == null)
        {
            super.onBackPressed();
        }
        else{
            loadTripData(trip);
        }

    }
}
